# GameState tracks almost every aspect of the game, all the constants are here
# The main game loop resides here
# key handling and chat commands reside here also


import libtcodpy as libtcod
from Player import Player
from Render import Render
from Render import InfoPanel
from Map import Map
from GameObject import Fighter
from Helpers import Helper
import Messages

SCREEN_WIDTH = 80
SCREEN_HEIGHT = 51
LIMIT_FPS = 20

class GameState:
    def __init__(self):
        self.SCREEN_WIDTH = SCREEN_WIDTH
        self.SCREEN_HEIGHT = SCREEN_HEIGHT
        self.LIMIT_FPS = LIMIT_FPS
        
        self.FOV_ALGO = 0
        self.FOV_LIGHT_WALLS = True
        self.TORCH_RADIUS = 10
        
        self.fov_map = []
        self.fov_recompute = False
        self.game_state = 'playing'
        
        fighter_component = Fighter(hp=30, defense=2, power=5, death_func=Helper.player_death)
        self.player = Player(self, self.SCREEN_WIDTH/2, self.SCREEN_HEIGHT/2, 
                             '@', "Player", libtcod.white, blocks=True, 
                             fighter=fighter_component)
        self.game_objects = [self.player]
         
        libtcod.console_set_custom_font('data/arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
        libtcod.console_init_root(self.SCREEN_WIDTH, self.SCREEN_HEIGHT, 'SimpleRoguelike', False)
        self.con = libtcod.console_new(self.SCREEN_WIDTH, self.SCREEN_HEIGHT)
        self.panel = InfoPanel(self)
        self.map = Map(self)
    
    def run_game(self):
        self.fov_map = libtcod.map_new(self.map.MAP_WIDTH, self.map.MAP_HEIGHT)
        
        for y in range(self.map.MAP_HEIGHT):
            for x in range(self.map.MAP_WIDTH):
                libtcod.map_set_properties(self.fov_map, x, y, not self.map.map[x][y].blocked, not self.map.map[x][y].block_sight)
        
        self.fov_recompute = True
        first_time = True  #for turn-based games
        player_action = None
        
        Messages.message('Enter mortal, and Perish.', libtcod.red)
        
        while not libtcod.console_is_window_closed():
            
            for game_obj in self.game_objects:
                game_obj.clear()
                
            #handle keys and exit game if needed
            if not first_time:  #for turn-based games, remember to indent after!
                player_action = self.handle_keys()
                if player_action == 'exit':
                    break
         
            first_time = False  #for turn-based games
            
            if self.game_state == 'playing' and player_action != 'no-turn':
                for game_obj in self.game_objects:
                    if game_obj.ai:
                        game_obj.ai.take_turn()
                        
            
            Render.render_all(self)
            libtcod.console_flush()
    
    def handle_keys(self):
        #key = libtcod.console_check_for_keypress()  #real-time
        key = libtcod.console_wait_for_keypress(True)  #turn-based
     
        if key.vk == libtcod.KEY_ENTER and key.lalt:
            #Alt+Enter: toggle fullscreen
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
        elif key.vk == libtcod.KEY_SPACE:
            #then they want to type in a command
            self.handle_command()
        elif key.c == ord('l'):
            Messages.message('Looking around you find nothing.', libtcod.dark_yellow)
        elif key.vk == libtcod.KEY_F1:
            Helper.gen_new_map(self)
        elif key.vk == libtcod.KEY_ESCAPE:
            return 'exit'  #exit game
     
        #movement keys
        if self.game_state == 'playing':
            if libtcod.console_is_key_pressed(libtcod.KEY_UP):
                self.player.move_or_attack(0,-1)
                self.fov_recompute = True
         
            elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
                self.player.move_or_attack(0, 1)
                self.fov_recompute = True
         
            elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT):
                self.player.move_or_attack(-1, 0)
                self.fov_recompute = True
         
            elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT):
                self.player.move_or_attack(1, 0)
                self.fov_recompute = True
            else:
                return 'no-turn'
    def handle_command(self):
        s=""
        prompt = "> "
        Render.render_all(self, chat=prompt+s)
        self.game_state = 'typing'
        while self.game_state == 'typing':
            key = libtcod.console_wait_for_keypress(True)
            if key.vk == libtcod.KEY_ENTER:
                self.game_state = 'playing'
                Messages.message('Player said: ' + s)
                break
            elif key.vk == libtcod.KEY_BACKSPACE:
                s = s[:-1]
                Render.render_all(self, chat=prompt+s)
            elif key.c:
                s += chr(key.c)
                Render.render_all(self, chat=prompt+s)